/**
 * @file MessageACK.cpp
 * @author Karol Kulesza
 *
 * Implementacja klasy odpowiadającej za obsługę potwierdzenia ACK otrzymanego od klienta.
 */

#include "MessageACK.h"
#include "../structures.h"
#include "../ClientController.h"
#include "../Log.h"
#include "../FileList.h"
#include "../MacCollector.h"

namespace tftp_server {

MessageACK::MessageACK(ClientController *clientController_, Package package_)
	:clientController(clientController_), package(package_)
{
	;

}

MessageACK::~MessageACK()
{
	;
	
}

void MessageACK::execute() const
{
	int recvblknum = package.block;
	int nextblknum = clientController->getNextBlockNumber();
	char sendbuff[512];

	if(recvblknum == nextblknum)
	{
		string str(clientController->getFileName());
		MAC mac = clientController->findMac(IP(clientController->getIp()));
		char mode = checkMode(clientController->getMode());
		if(mode == 'o')
		{
			Loger::getInstance().send(Log("MessageACK: wrong mode recieved from client: " + clientController->getIp(), 2));
			Package errorPackage;
			char temp[] = "wrong mode recieved";
			errorPackage.setError(ERR_BADOP,temp);
			clientController->send(errorPackage);
			clientController->exit(-1);
			return;
		}
		File* file = FileList::getInstance().getFile(clientController->getIp(), mac, str, mode);
		if(file->isNull())
		{
		    Loger::getInstance().send(Log("MessageACK: File " + string(clientController->getFileName()) + 
		    		" is Null, client IP: " + clientController->getIp(), 2));
		    Package errorPackage;
		    char temp[] = "File is Null";
		    errorPackage.setError(ERR_ACCESS,temp);
		    clientController->send(errorPackage);
		    clientController->exit(-1);
		    return;
		}
		
		if(!file->isExist())
		{
			Loger::getInstance().send(Log("MessageACK: File " + string(clientController->getFileName()) 
					+ " not found, client IP: " + clientController->getIp(), 2));
			Package errorPackage;
			char temp[] = "File not found";
			errorPackage.setError(ERR_NOFILE,temp);
			clientController->send(errorPackage);
			clientController->exit(-1);
			return;
		}

		if(!file->isAccessible())
		{
			Loger::getInstance().send(Log("MessageACK: Access violation to File " + string(clientController->getFileName()) 
					+ ", client IP: " + clientController->getIp(), 2));
			Package errorPackage;
			char temp[] = "Access violation";
			errorPackage.setError(ERR_ACCESS,temp);
			clientController->send(errorPackage);
			clientController->exit(-1);
			return;
		}
		int size = file->getFragment(MAXDATA*recvblknum, MAXDATA, sendbuff);

		if(size == 0)
		{
			if(clientController->getLastSend() < MAXDATA)
			{
				Loger::getInstance().send(Log("MessageACK: File " + string(clientController->getFileName()) 
						+ " transfer finished to client: " + clientController->getIp(),3));
				clientController->exit(0);
				return;
			}		
		}

		int temp = nextblknum+1;
		clientController->setLastSend(size);
		clientController->setNextBlockNumber(temp);
		Package dataPackage;
		dataPackage.setData(temp, sendbuff, size);
		clientController->send(dataPackage);
		delete file;
	}
	else if(recvblknum < nextblknum-1)
	{
		Loger::getInstance().send(Log("MessageACK: Block number in ACK < expected block number - 1, client IP: "
				+ clientController->getIp(), 3));
	}
	else if(recvblknum > nextblknum)
	{
		Loger::getInstance().send(Log("MessageACK: Block number in ACK > expected  block number, client IP: "
				+ clientController->getIp(), 3));
	}
	else
		;
		//przypadek ucznia czarnoksieznika, nie robimy nic
}


}
